home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
A.C.E. 2
/
ACE CD 2.iso
/
FILES
/
UTILS
/
AMOS3.DMS
/
AMOS3.adf
/
Extensions
/
Music.s
< prev
next >
Wrap
Text File
|
1978-10-10
|
43KB
|
2,055 lines
Include "Equ.s"
Translate equ -30
******************************************************************
* ** * * **** **** *** ** **** *** ***
* * * ** ** * * * * * * * * * *
* **** * ** * * * **** **** **** **** * *
* * * * * * * * * * * * * * *
* * * * * **** **** **** * * **** *** ***
******************************************************************
*
* AMOS MUSICAL ROUTINES
*
* Version 1.1
* By Francois Lionet
* AMOS (c) Mandarin / Jawx 1990
*
* This source code is public domain
*
******************************************************************
*
* Here is the main AMOS extension. It includes all music
* instructions, and is a perfect example of how to create a
* extension for AMOS.
* It has been assembled with GENAM2.
*
* This code is certainely not perfect, some parts may seem to
* you improvable, and sure are! If you make changes to it, be sure
* keep compatibility with the previous version. Create a version for
* each new change so that AMOS music extension don`t become a
* jungle!
* Some labels may look rather French to you, but sorry, it is
* my native language!
*
* When you program an extension, try to program it in RELATIVE
* code, using adress register and index. The COMPILER will only
* accept relative code.
*
* Thanks to Andreas Tadic, the author of GMC for inspiration in
* some parts of the music routine...
*
******************************************************************
******************************************************************
* AMOS INTERFACE
******* COLD START
* This must be at the beginning of your program!
* It is called just after loading...
*
* On Entry:
* A0= Branch table
* A1= Current intuition.library base
* A2= Current graphic.library base
* A3= Current diskfont.library base
* A5= AMOS data zone address
* You must return
* A0= Token table
* A1= Welcome message
* A2= Routine called by screen reset
* A3= Routine called on Quit
* D0= False/true-> ERROR
* D1= Number of extension. This number MUST be the same
* than the extension number in the extension list
* D2= Address of a routine called each time a memory bank
* has been changed, zero if not to be called
*
* If D1<>number of extension or D0=true, AMOS does not load!
*
movem.l a4-a6,-(sp)
* If AMOS data zone, stands 8 long words allowing you to simply
* put a patch in the VBL interrupt. The first on is at VBLRout.
* At each VBL, AMOS explores this list, and call all address <> 0
* It stops at the FIRST zero. The music patch is the first routine
* called.
lea MusInt(pc),a1 * Interrupt routine
move.l a1,VBLRout(a5) * Branch
lea MusAdr(pc),a1
move.l a0,(a1) * Store address of BRANCH TABLE
lea MB(pc),a3 * Base of music parameters
lea BkCheck(pc),a0 * Address of CHECK MUSIC BANK
move.l a0,d2
lea AdMB(pc),a1
move.l a3,(a1)
lea Tk(pc),a0 * Address of TOKEN TABLE
lea MusWel(pc),a1 * Address of WELCOME MESSAGE
lea MusDef(pc),a2 * Address of SCREEN RESET
lea MusEnd(pc),a3 * Address of QUIT
moveq #0,d1 * Returns NUMBER OF EXTENSION
movem.l (sp)+,a4-a6
moveq #0,d0 * NO ERRORS
rts
******* SCREEN RESET
* Each time a DEFAULT occurs, this routine is called. If you
* do not want any effect, make it point to a RTS
MusDef:
lea MB(pc),a3
* Init narrator
bsr NarInit
* Init musique
bsr RazWave * Reset waves
move.l Buffer(a5),a0 * Draw square wave
move.l a0,a1
moveq #127,d0
MuDf1 move.b #-127,128(a0)
move.b #127,(a0)+
dbra d0,MuDf1
moveq #0,d1 * 0-> Noise
bsr NeWave
moveq #1,d1 * 1-> Square wave
bsr NeWave
move.w #LNoise/2-1,d2 * Draw first noise
move.w BSeed-MB(a3),d1
move.l WaveBase-MB(a3),a0
lea WaveDeb(a0),a0
MuDf2 add.w Circuits+6,d1
mulu #$3171,d1
lsr.l #8,d1
move.w d1,(a0)+
dbra d2,MuDf2
move.w d1,BSeed-MB(a3)
moveq #56,d0 * Default settings
moveq #%1111,d1
bsr Vol
bsr MVol
move.w #5,SamBank-MB(a3) * Sample bank=5
moveq #0,d0 * Sam loop off
moveq #-1,d1
bsr SL0
bsr MuInit
rts
******* QUIT
* Here you should restore everything to normal, close
* all opened libraries, give all reserved memory back to
* the system...
MusEnd: lea MB(pc),a3
* Plus de routine VBL
clr.l VBLRout(a5) * No more routine
* End narrator (if there)
tst.l TranBase-MB(a3)
beq.s NarEnd
lea WriteRep-MB(a3),a1
move.l $4,a6
jsr RemPort(a6)
lea TalkIO-MB(a3),a1
jsr CloseDev(a6)
move.l TranBase-MB(a3),a1
jsr CloseLib(a6)
* End music
NarEnd bsr MOff
moveq #%1111,d0
bsr EnvOff
bsr RazWave
lea Circuits,a0
move.w #$000F,DmaCon(a0)
move.w #%0000011110000000,IntReq(a0)
move.w #%0000011110000000,IntEna(a0)
clr.w $a8(a0)
clr.w $b8(a0)
clr.w $c8(a0)
clr.w $d8(a0)
rts
******* Now follow a tricky thing to allow AMAL to grab the address
* of the vumeters. AMAL will get the address of the music extension
* BkCheck routine, look 4 bytes before, and get the address of the
* voices volume level
AdMB dc.l 0
******* LOOK FOR MUSIC BANK
* Authorised registers: D0-D7/A0-A3
BkCheck lea MB(pc),a3
move.l MusBank-MB(a3),d0 * Address of OLD music bank
move.l 2*8(a0),d1 * Address of ACTUAL music bank
beq.s BkNo * 8 bytes per bank (here bank 3)
move.l d1,a1 * Looks for "Musi"
move.l (a1),d2
cmp.l BkMus-MB(a3),d2
bne.s BkNo
lea 8(a1),a1
moveq #0,d1 * Performs a check sum
add.l (a1),d1
add.l 4(a1),d1
add.l 8(a1),d1
add.l 12(a1),d1
cmp.l d0,a1
bne.s BkNew
cmp.l MusCheck-MB(a3),d1
bne.s BkNew
* Same bank! Do nothing!
rts
* No more bank!
BkNo tst.l d0
beq.s BkNo1
bsr MuInit
clr.l MusBank-MB(a3)
BkNo1 rts
* A NEW bank
BkNew move.l a1,MusBank-MB(a3)
move.l d1,MusCheck-MB(a3)
bsr MuInit
move.l MusBank-MB(a3),a0
move.l a0,a1
add.l (a0),a1
move.l a1,BankInst-MB(a3)
move.l a0,a1
add.l 4(a0),a1
move.l a1,BankSong-MB(a3)
add.l 8(a0),a0
move.l a0,BankPat-MB(a3)
rts
******* Call normal error messages
OOMem moveq #24,d0 * Out of mem
bra.s IError
IFonc: moveq #23,d0 * Function call
IError: move.l MusAdr(pc),a0 * No need to care about SP!
jmp 4(a0)
******* Call customized error messages
WNDef moveq #0,d0
bra.s Custom
SNDef moveq #1,d0
bra.s Custom
BNSam moveq #2,d0
bra.s Custom
STSho moveq #3,d0
bra.s Custom
W0Res moveq #4,d0
bra.s Custom
MnRes moveq #5,d0
bra.s Custom
MNDef moveq #6,d0
Custom: moveq #0,d1 * Error can be trapped
lea MusErr(pc),a0 * Your list
move.l MusAdr(pc),a1
jmp 8(a1)
******* Debugging facility
* If you call this routine, it restore screen, leaves
* everything opened, and do an ILLEGAL instruction to come back
* to MONAM2. A0 holds the current PC address, do just do a PC=A0
* to come just after the JSR IBUG!
* Really usefull for annoying bugs! Of course, you can't call
* it under insterrupts, and you have to do a RESET after...
IBug: move.l MusAdr(pc),a0
jmp (a0)
***********************************************************
* Now, the code!
*
* How to get the parameters?
*
* When an instruction or function is called, you get the parameters
* pushed in A3. Remember that you unpile them in REVERSE order than
* the instruction syntax.
* As you have a entry point for each set of parameters, you know
* how many are pushed...
* - INTEGER: move.l (a3)+,d0
* - STRING: move.l (a3)+,a0
* move.w (a0)+,d0
* A0---> start of the string.
* D0---> length of the string
* - FLOAT: move.l (a3)+,d0
* fast floatting point format.
* IMPORTANT POINT: you MUST unpile the EXACT number of parameters,
* to restore A3 to its original level. If you do not, you will not
* have a immediate error, and AMOS will certainely crash on next
* UNTIL / WEND / ENDIF / NEXT etc... You do not have to care about it
* when an error occurs...
*
* You must preserve A4 to A6. All other registers can be freely
* modified.
* You end a routine by a RTS.
*
* To send a function`s parameter back to AMOS, you load it in D3,
* and put its type in D2:
* moveq #0,d2 for an integer
* moveq #1,d2 for a float
* moveq #2,d2 for a string
*
* THE JUMP TABLE
*
* The address given to you during initialisation process
* points to a usefull BRA table, to have quick access to some
* important AMOS routines. Here are the offsets of this routines:
*
* bra JBug ;00- Debugging facility
* bra RunErr ;04- Normal error
* bra ERunErr ;08- Specific error
* bra BkAd ;0C- D3.l (number of bank-1)->A0 Bank address
* bra Tests ;10- Performs update
* bra WaitRout ;14- Wait routine (see play)
* bra GetEc ;18- Get screen address D0.l= screen number
* bra AdOuBank ;1C- Address or memory bank? (D3.l)
* bra EffBank ;20- Erases bank #D3.l
*
***********************************************************
* NARRATOR!
* This part of code is certainely perfectible, as it is not
* really "safe"...
******* Open narrator
OpNar move.l TranBase(pc),d0
bne.s OpNarOk
movem.l a3-a6,-(sp)
lea MB(pc),a3
sub.l a1,a1 * Narrator.device
move.l $4,a6
jsr FindTask(a6)
lea WriteRep-MB(a3),a1
move.l d0,$10(a1)
jsr AddPort(a6)
lea TalkIo-MB(a3),a1
moveq #0,d0
moveq #0,d1
lea NarDevice-MB(a3),a0
jsr OpenDev(a6)
tst.l d0
bne OpNarE
bsr NarInit
lea TranName-MB(a3),a1 * Translator.library
moveq #0,d0
jsr OpenLib(a6)
move.l d0,TranBase-MB(a3)
beq OpNarE
movem.l (sp)+,a3-a6
OpNarOk rts
OpNarE movem.l (sp)+,a3-a6
NoNar moveq #7,d0
bra Custom
******* Init narrator (if here)!
NarInit lea TalkIO-MB(a3),a1
lea WriteRep-MB(a3),a0
move.l a0,14(a1)
move.w #150,48(a1)
move.w #110,50(a1)
clr.w 52(a1)
clr.w 54(a1)
lea Amaps-MB(a3),a0
move.l a0,56(a1)
move.w #4,60(a1)
move.w #63,62(a1)
move.w #22200,64(a1)
rts
******* SAY a$[,multi]
ISay2: bsr OpNar
move.l (a3)+,d7
bra.s ISay
ISay1: bsr OpNar
moveq #0,d7
ISay: moveq #%0000,d0
bsr VOnOf
lea MB(pc),a0
clr.w EnvOn-MB(a0)
clr.w Noise-MB(a0)
move.l (a3)+,a0
moveq #0,d0
move.w (a0)+,d0
move.l Buffer(a5),a1
move.l #1024,d1
movem.l a3-a6,-(sp)
move.l TranBase(pc),a6
jsr Translate(a6)
tst.w d0
bne.s SayX
lea TalkIO(pc),a1
move.w #3,28(a1)
move.l #1024,36(a1)
move.l Buffer(a5),40(a1)
move.l ExecBase,a6
tst.w d7
bne.s ISayA
jsr DoIO(a6)
bra.s SayX
ISayA jsr SendIO(a6)
SayX movem.l (sp)+,a3-a6
moveq #%1111,d0
bsr VOnOf
rts
******* SET TALK sex,mode,pitch,rate
ITalk bsr OpNar
move.l #EntNul,d0
lea TalkIO(pc),a1
move.l (a3)+,d1
cmp.l d0,d1
beq.s IRd1
cmp.w #40,d1
bcs IFonc
cmp.w #400,d1
bhi IFonc
move.w d1,48(a1)
IRd1 move.l (a3)+,d1
cmp.l d0,d1
beq.s IRd2
cmp.w #65,d1
bcs IFonc
cmp.w #320,d1
bhi IFonc
move.w d1,50(a1)
IRd2 move.l (a3)+,d1
cmp.l d0,d1
beq.s IRd3
and.w #$0001,d1
move.w d1,52(a1)
IRd3 move.l (a3)+,d1
cmp.l d0,d1
beq.s IRd4
and.w #$0001,d1
move.w d1,54(a1)
IRd4 rts
***********************************************************
* MUSIC INSTRUCTION
******* BELL
Bell0 moveq #0,d3
moveq #70,d2
moveq #%1111,d1
moveq #1,d5
lea EnvBell(pc),a0
move.l a0,d6
bra GoBel
Bell1 moveq #0,d3
move.l (a3)+,d2
moveq #%1111,d1
moveq #1,d5
lea EnvBell(pc),a0
move.l a0,d6
bra GoBel
******* BOOM
Boom moveq #0,d3
moveq #36,d2
moveq #0,d5
lea EnvBoom(pc),a0
move.l a0,d6
bra.s Shout
******* SHOOT
Shoot moveq #0,d3
moveq #60,d2
moveq #0,d5
lea EnvShoot(pc),a0
move.l a0,d6
* Gives a stereo effect
Shout: clr.w d0
bsr VOnOf
moveq #%1000,d1
Shot movem.l d0-d7,-(sp)
bsr GoShot
movem.l (sp)+,d0-d7
addq.w #1,d2
lsr.w #1,d1
bcc.s Shot
rts
******* VOLUME n
IVol1 move.l (a3)+,d0
moveq #%1111,d1
bsr Vol
bsr MVol
rts
******* VOLUME voice,n
IVol2 move.l (a3)+,d0
move.l (a3)+,d1
* Set voices volume level
Vol cmp.l #64,d0
bcc IFonc
moveq #0,d2
lea EnvBase(pc),a0
Vol1 btst d2,d1
beq.s Vol2
move.w d0,EnvDVol(a0)
Vol2 lea EnvLong(a0),a0
addq.w #1,d2
cmp.w #4,d2
bcs.s Vol1
rts
******* PLAY note,length
IPlay2 move.l (a3)+,d3
bmi IFonc
move.l (a3)+,d2
moveq #%1111,d1
moveq #-1,d5
moveq #0,d6
bra.s GoBel
******* Play voice,note,length
IPlay3 move.l (a3)+,d3
bmi IFonc
move.l (a3)+,d2
move.l (a3)+,d1
moveq #-1,d5
moveq #0,d6
GoBel cmp.l #96,d2 * <96?
bhi IFonc
move.w d1,d0 * Stop voices
eor.w #$000F,d0
bsr VOnOf
GoShot move.l a3,-(sp)
lea Circuits,a2
lea MB(pc),a3
move.w EnvOn-MB(a3),d7
clr.w EnvOn-MB(a3)
* Explores all 4 voices
moveq #0,d0
move.w d1,d4
moveq #3,d1
IPl1 btst d1,d4
beq.s IPl2
bsr VPlay
IPl2 dbra d1,IPl1
******* Start!
IPlX move.w #$1f4,d1
IPlX0 dbra d1,IPlX0
bset #15,d0
move.w d0,DmaCon(a2)
move.w d7,EnvOn-MB(a3)
move.l (sp)+,a3
* Wait?
tst.l d3
beq.s IPlX1
move.l MusAdr(pc),a0 * Call the AMOS wait routine
jsr $14(a0)
IPlX1 rts
******* Play voice D1: WAVE orSAMPLE
* Note D2
VPlay movem.l d0-d7/a0-a2,-(sp)
bclr d1,Noise-MB(a3) * No more random
tst.w d2
beq VSil
addq.w #3,d2
move.w d5,d0 * Forced wave? (bell)
bpl.s VPl0
move.w d1,d0 * Wave or Sample?
lsl.w #1,d0
lea Waves(pc),a0
move.w 0(a0,d0.w),d0
bmi VPl2
* Play WAVE!
VPl0 beq VPl4
moveq #0,d3
bset d1,d3
move.w d3,DmaCon(a2) * Stop voice
lea $a0(a2),a2
move.w d1,d3
lsl.w #4,d3
add.w d3,a2 * a2-> I/O
movem.l d1-d3/a2,-(sp)
move.w d0,d1
bsr WaveAd
beq WNDef
move.l a2,a1
movem.l (sp)+,d1-d3/a2
pea WaveEnv(a1)
lea WaveDeb(a1),a1
subq.w #1,d2
move.w d2,d3
ext.l d3
divu #12,d3
lsl.w #2,d3
lea TFreq-MB(a3),a0
add.w d3,a0
add.w (a0)+,a1
move.l a1,(a2) * AudAd
move.w (a0)+,d3
move.w d3,4(a2) * AudLen
lsl.w #1,d3
lea TNotes-MB(a3),a1
lsl.w #1,d2
mulu 0(a1,d2.w),d3
move.l MusClock-MB(a3),d2
divu d3,d2
cmp.w #124,d2
bcc.s VPl1
moveq #124,d2
VPl1: move.w d2,6(a2) * AudPer
* Start enveloppe
move.l (sp)+,d5
tst.l d6 * Fixed enveloppe? (bell / shoot)
bne.s VPl1a
move.l d5,d6
VPl1a lea EnvBase-MB(a3),a0
move.w d1,d0
mulu #EnvLong,d0
add.w d0,a0
move.l d6,EnvAd(a0)
move.l d6,EnvDeb(a0)
clr.w EnvVol(a0)
bsr MuIntE
movem.l (sp)+,a0-a2/d0-d7
bset d1,d0
bset d1,d7
rts
******* Silence!
VSil moveq #0,d0
bset d1,d0
move.w d0,DmaCon(a2)
movem.l (sp)+,a0-a2/d0-d7
bclr d1,d7
rts
******* Play SAMPLE
VPl2 move.l a2,-(sp)
move.w d2,-(sp)
neg.w d0
bsr GetSam
move.w (sp)+,d0
move.l (sp)+,a2
VPl3 lea TNotes-MB(a3),a0
lsl.w #1,d0
mulu -2(a0,d0.w),d3
divu #440,d3
bra SPl0
******* Play NOISE
VPl4 bset d1,Noise-MB(a3)
move.w d2,d0
move.l WaveBase-MB(a3),a1
lea WaveEnv(a1),a0
lea WaveDeb(a1),a1
move.l #LNoise,d2
move.l #2000,d3
tst.l d6
bne.s VPl3
move.l a0,d6
bra.s VPl3
******* PLAY OFF (voice)
IPlOf0 moveq #%1111,d0
bra.s PlOf
IPlOf1 move.l (a3)+,d0
PlOf move.l a3,-(sp)
lea MB(pc),a3
bsr EnvOff
move.l (sp)+,a3
rts
***********************************************************
* SAMPLE INSTRUCTIONS
******* SAM BANK n
ISBank move.l (a3)+,d0
bls IFonc
cmp.l #16,d0
bhi IFonc
lea SamBank(pc),a0
move.w d0,(a0)
rts
******* SAMLOOP ON
ISLOn1 moveq #-1,d0
SLoop move.l (a3)+,d1
bra.s Sl0
ISLOn0 moveq #-1,d0
moveq #%1111,d1
bra.s Sl0
******* SAMLOOP OFF
ISLOf1 moveq #0,d0
move.l (a3)+,d1
bra.s Sl0
ISLOf0 moveq #0,d0
moveq #%1111,d1
SL0 moveq #0,d2
lea EnvSam(pc),a0
Sl1 btst d2,d1
beq.s Sl2
move.w d0,8(a0)
Sl2 lea $10(a0),a0
addq.w #1,d2
cmp.w #4,d2
bcs.s Sl1
rts
******* NOISE TO voice
INoTo move.l (a3)+,d1
moveq #0,d0
bra.s ISmt
******* SAMPLE n TO voice
ISamTo move.l 4(a3),d0
bsr GetSam
move.l (a3)+,d1
move.l (a3)+,d0
neg.w d0
* Poke D1-> waves
ISmt lea Waves(pc),a0
moveq #0,d2
ISmt1 btst d2,d1
beq.s ISmt2
move.w d0,(a0)
ISmt2 addq.l #2,a0
addq.w #1,d2
cmp.w #4,d2
bcs.s ISmt1
rts
******* SAM PLAY number
ISam1 move.l (a3)+,d0
bsr GetSam
moveq #%1111,d1
moveq #0,d6
bra GoSam
******* SAM PLAY voix,number
ISam2 move.l (a3)+,d0
bsr GetSam
move.l (a3)+,d1
moveq #0,d6
bra GoSam
******* SAM PLAY voix,number,frequence
ISam3 move.l 4(a3),d0
bsr GetSam
move.l (a3)+,d3
cmp.l #500,d3
ble IFonc
addq.l #4,a3
move.l (a3)+,d1
moveq #0,d6
bra GoSam
******* SAM RAW voice,ad,length,freq
ISamR move.l (a3)+,d3
cmp.l #500,d3
ble IFonc
move.l (a3)+,d2
cmp.l #256,d2
ble IFonc
move.l (a3)+,a1
move.l (a3)+,d1
moveq #0,d6
GoSam: move.l a3,-(sp)
lea MB(pc),a3
move.w d1,d0 * Stops music
eor.w #$000F,d0
bsr VOnOf
lea Circuits,a2
move.w EnvOn-MB(a3),d7
clr.w EnvOn-MB(a3)
* Do all voices
moveq #0,d0
move.w d1,d4
moveq #3,d1
ISp2b btst d1,d4
beq.s ISp2c
bsr SPlay
ISp2c dbra d1,ISp2b
* Start!
ISpX move.w #$1f4,d1
ISpX1 dbra d1,ISpX1
bset #15,d0
move.w d0,DmaCon(a2)
move.w d7,EnvOn-MB(a3)
move.l (sp)+,a3
rts
******* Find a sample -> A0
GetSam move.l d0,-(sp)
move.w SamBank(pc),d3
ext.l d3
beq IFonc
move.l MusAdr(pc),a0
jsr $0C(a0)
move.l -8(a0),d0
cmp.l BkSam(pc),d0
bne BNSam
* Get sample characteristics1
move.l (sp)+,d0
bls IFonc
cmp.w (a0),d0
bhi SNDef
lsl.w #2,d0
move.l 2-4(a0,d0.w),d0
beq SNDef
add.l d0,a0
move.w 8(a0),d3
ext.l d3
move.l 10(a0),d2
lea 14(a0),a1
rts
******* SAMPLAY routine
* A1= Sample
* D3= Freq
* D2= Long
* D1= Voice
SPlay: movem.l d0-d7/a0-a2,-(sp)
bclr d1,Noise-MB(a3)
SPl0 moveq #0,d0
bset d1,d0 * Stop voice
move.w d0,DmaCon(a2)
lea $a0(a2),a2
move.w d1,d4
lsl.w #4,d4
add.w d4,a2 * a2-> I/O
move.l a1,(a2) * AudAd
move.w d2,d4
lsr.w #1,d4
move.w d4,4(a2) * AudLen
move.l MusClock-MB(a3),d4
divu d3,d4
bvc.s SPl1
moveq #124,d4
SPl1 cmp.w #124,d4
bcc.s SPl2
moveq #124,d4
SPl2: move.w d4,6(a2) * AudPer
* Starts enveloppe
move.l d6,a1
tst.l d6
bne SPl4
lea EnvSam-MB(a3),a1
move.w d1,d0
lsl.w #4,d0
add.w d0,a1
mulu #50,d2
divu d3,d2
subq.w #1,d2
bhi.s SPl3
moveq #1,d2
SPl3 move.w d2,4(a1)
SPl4 lea EnvBase-MB(a3),a0
move.w d1,d0
mulu #EnvLong,d0
add.w d0,a0
move.l a1,EnvAd(a0)
move.l a1,EnvDeb(a0)
clr.w EnvVol(a0)
bsr MuIntE
* Fini!
movem.l (sp)+,d0-d7/a0-a2
bset d1,d0
bset d1,d7
rts
***********************************************************
* WAVE INSTRUCTION SET
******* WAVE n TO n
IWave: move.l 4(a3),d1
bmi IFonc
bsr WaveAd
beq WNDef
move.l (a3)+,d1
move.l (a3)+,d0
bra ISmt
******* SET WAVE n,a$
ISWave: move.l (a3)+,a1
move.w (a1)+,d1
cmp.w #256,d1
bcs STSho
move.l (a3)+,d1
bls IFonc
move.l a3,-(sp)
lea MB(pc),a3
bsr NeWave
bne OOMem
move.l (sp)+,a3
rts
******* DEL WAVE
IDWave1 move.l (a3)+,d1
bmi IFonc
beq W0Res
cmp.l #1,d1
beq W0Res
move.l a3,-(sp)
lea MB(pc),a3
moveq #%1111,d0
bsr EnvOff
bsr WaveAd
beq WNDef
bsr WaveDel
bsr NoWave
move.l (sp)+,a3
rts
******* SET ENVEL n,n TO n,v
ISEnv move.l (a3)+,d4
cmp.l #64,d4
bcc IFonc
move.l (a3)+,d3
move.l (a3)+,d5
bmi IFonc
cmp.l #7,d5
bcc IFonc
move.l (a3)+,d1
bmi IFonc
tst.w d5
bne.s ISe1
tst.w d3
bls IFonc
ISe1 move.l a3,-(sp)
lea MB(pc),a3
bsr WaveAd
beq WNDef
lsl.w #2,d5
lea WaveEnv(a2,d5.w),a2
move.w d3,(a2)+
move.w d4,(a2)+
clr.w (a2)
move.l (sp)+,a3
rts
******* RAZ WAVES
RazWave movem.l a2/d0-d2,-(sp)
moveq #%1111,d0
bsr EnvOff * Stop all voices
lea WaveBase-MB(a3),a2 * Erase all instruments
move.l a2,d2
RzW1 move.l d2,a2
move.l (a2),d0
beq.s RzW2
move.l d0,a2
bsr WaveDel
bra.s RzW1
RzW2 bsr NoWave
movem.l (sp)+,a2/d0-d2
rts
* Plus de Waves speciales
NoWave lea Waves(pc),a0 * Default waves
move.w #1,(a0)+
move.w #1,(a0)+
move.w #1,(a0)+
move.w #1,(a0)+
rts
******* NEW WAVES
* A1= Array address
* D1= # to create
NeWave: movem.l d1-d7/a1-a2,-(sp)
NeW0 bsr WaveAd
beq.s NeW1
moveq #%1111,d0
bsr EnvOff
bsr WaveDel
bra.s NeW0
NeW1 move.l #WaveLong,d0
SyCall SyChip
beq.s NeWE
move.l d0,(a2)
move.l d0,a2
move.w d1,WaveNb(a2)
* Copy default ADSR
move.l a1,-(sp)
lea EnvDef-MB(a3),a0
lea WaveEnv(a2),a1
NeW3 move.l (a0)+,(a1)+
bne.s NeW3
move.l (sp)+,a1
* Full wave: 256 bytes
lea WaveDeb(a2),a2
move.l a2,a0
moveq #256/4-1,d0
NeW2 move.l (a1)+,(a0)+
dbra d0,NeW2
* 1/2
move.l a2,a1
move.l a0,a2
moveq #127,d0
bsr NewRout
* 1/4
move.l a2,a1
move.l a0,a2
moveq #63,d0
bsr NewRout
* 1/8
move.l a2,a1
move.l a0,a2
moveq #31,d0
bsr NewRout
* 1/16
move.l a2,a1
move.l a0,a2
moveq #15,d0
bsr NewRout
* 1/32
move.l a2,a1
move.l a0,a2
moveq #7,d0
bsr NewRout
* 1/64
move.l a2,a1
move.l a0,a2
moveq #3,d0
bsr NewRout
******* No error
moveq #0,d0
NeWx movem.l (sp)+,d1-d7/a1-a2
rts
******* Out of mem
NeWE moveq #-1,d0
bra.s NeWx
******* Divide a sample by 2
NewRout move.b (a1)+,d1
ext.w d1
move.b (a1)+,d2
ext.w d2
add.w d2,d1
asr.w #1,d1
move.b d1,(a0)+
dbra d0,NewRout
rts
******* Get a wave address
WaveAd: moveq #0,d2
lea WaveBase(pc),a2
move.l (a2),d0
beq.s WAd2
WAd1 move.l a2,d2
move.l d0,a2
cmp.w WaveNb(a2),d1
beq.s WAd3
move.l (a2),d0
bne.s WAd1
WAd2 moveq #0,d0
rts
WAd3 moveq #-1,d0
rts
******* Deletion of a WAVE (A2)-D2
WaveDel movem.l a0-a2/d0-d2,-(sp)
move.w WaveNb(a2),d1
move.l d2,a0
move.l (a2),(a0)
move.l #WaveLong,d0
move.l a2,a1
SyCall SyFree
movem.l (sp)+,a0-a2/d0-d2
rts
***********************************************************
* ENVELOPPES
***********************************************************
* STOP ENVELOPPE D0
EnvOff movem.l d0-d3/a0,-(sp)
move.w EnvOn-MB(a3),d1
clr.w EnvOn-MB(a3)
moveq #0,d3
lea Circuits,a0
moveq #0,d2
EOf1 btst d2,d0
beq.s EOf2
bclr d2,d1
beq.s EOf2
bset d2,d3
move.w #2,$a4(a0)
clr.w $a8(a0)
EOf2 lea $10(a0),a0
addq.w #1,d2
cmp.w #4,d2
bcs.s EOf1
move.w d1,EnvOn-MB(a3)
move.w d3,MuReStart-MB(a3)
movem.l (sp)+,d0-d3/a0
rts
******* Next enveloppe
MuIntE move.l EnvAd(a0),a1
MuIe0 move.w (a1)+,d3
beq.s MuIntS
bmi.s MuIe1
move.w d3,EnvNb(a0)
move.w EnvDVol(a0),d4
mulu (a1)+,d4
lsr.w #6,d4
sub.w EnvVol(a0),d4
ext.l d4
lsl.w #8,d4
divs d3,d4
ext.l d4
lsl.l #8,d4
move.l d4,EnvDelta(a0)
clr.w EnvVol+2(a0)
move.l a1,EnvAd(a0)
rts
* Loop
MuIe1 move.l EnvDeb(a0),a1
bra.s MuIe0
* End of a voice
MuIntS bset d1,d5
bclr d1,d0
bclr d1,Noise-MB(a3)
* Restarts the music
bset d1,MuReStart+1-MB(a3)
rts
******************************************************************
* MUSIC
******* Music initialisation
MuInit: clr.l MuBase-MB(a3)
clr.w MuNumber-MB(a3)
move.l #$DFF0A0,MuChip0-MB(a3)
move.l #$DFF0B0,MuChip1-MB(a3)
move.l #$DFF0C0,MuChip2-MB(a3)
move.l #$DFF0D0,MuChip3-MB(a3)
move.w #$000F,MuDMAsk-MB(a3)
clr.w MuReStart-MB(a3)
bsr MOff
rts
******* MUSIC OFF-> Stops all musics
IMuSOff movem.l a0-a3/d0-d1,-(sp)
lea MB(pc),a3
clr.l MuBase-MB(a3)
clr.w MuNumber-MB(a3)
bsr MOff
movem.l (sp)+,a0-a3/d0-d1
rts
******* MUSIC STOP-> Stops current music
IMuStop movem.l a0-a3/d0-d1,-(sp)
lea MB(pc),a3
move.l MuBase-MB(a3),d0
beq.s IStp
clr.w MuBase-MB(a3)
move.l d0,a0
clr.w VoiCpt0(a0)
clr.w VoiCpt1(a0)
clr.w VoiCpt2(a0)
clr.w VoiCpt3(a0)
move.l d0,MuBase-MB(a3)
IStp movem.l (sp)+,a0-a3/d0-d1
rts
******* MUSIC VOLUME
IMVol move.l (a3)+,d0
cmp.l #64,d0
bcc IFonc
* Set volume
MVol and.w #63,d0
lea MB(pc),a0
move.w d0,MuVolume-MB(a0)
move.l MuBase-MB(a0),d4
beq.s MVol3
clr.l MuBase-MB(a0)
lea MuBuffer-MB(a0),a1
move.w MuNumber-MB(a0),d1
MVol0 move.l a1,a2
moveq #3,d2
MVol1 move.w VoiDVol(a2),d3
mulu d0,d3
lsr.w #6,d3
move.w d3,VoiVol(a2)
lea VoiLong(a2),a2
dbra d2,MVol1
MVol2 lea MuLong(a1),a1
subq.w #1,d1
bne.s MVol0
move.l d4,MuBase-MB(a0)
MVol3 rts
******* VOICE ON/OFF Voices
IVoice move.l (a3)+,d0
and.w #$000F,d0
move.l a3,-(sp)
lea MB(pc),a3
bsr VOnOf
movem.l (sp)+,a3
rts
******* Start / Stop voices D0
VOnOf movem.l d0-d5/a0-a3,-(sp)
lea MB(pc),a3
move.l MuBase-MB(a3),d1
beq.s VooX
clr.l MuBase-MB(a3)
move.l d1,a1
move.l d1,a2
move.w MuDMAsk-MB(a3),d1
move.w d0,MuDMAsk-MB(a3)
move.l WaveBase-MB(a3),a0
lea WaveDeb(a0),a0
move.l a0,d3
lea MuChip0-MB(a3),a0
moveq #0,d2
moveq #0,d4
* Exploration loop
Voo1 btst d2,d0
bne.s Voo2
* Stop a voice!
btst d2,d1 * Already stopped?
beq.s VooN
bset d2,d4
move.l d3,(a0)
bclr d2,MuStart+1(a2)
bclr d2,MuStop+1(a2)
bra.s VooN
* Re start a voice
Voo2 btst d2,d1 * Already on?
bne.s VooN
bset d2,MuReStart+1-MB(a3)
* Next
VooN addq.l #4,a0
lea VoiLong(a1),a1
addq.w #1,d2
cmp.w #4,d2
bcs.s Voo1
* Stop them!
move.w d4,Circuits+DmaCon
move.w #$200,d0
VooW dbra d0,VooW
move.l a2,MuBase-MB(a3)
VooX movem.l (sp)+,d0-d5/a0-a3
rts
******* MUSIC n
IMusic move.l (a3)+,d3
bls IFonc
* Points to the SONG
move.l a3,-(sp)
lea MB(pc),a3
tst.l MusBank-MB(a3)
beq MnRes
move.l BankSong-MB(a3),a1
cmp.w (a1),d3
bhi MNDef
lsl.w #2,d3
add.l 2-4(a1,d3.w),a1
* Still room?
cmp.w #3,MuNumber-MB(a3)
bcc IMusX
clr.l MuBase-MB(a3)
* Buffer address
move.w MuNumber-MB(a3),d0
move.w d0,d1
addq.w #1,MuNumber-MB(a3)
mulu #MuLong,d0
lea MuBuffer-MB(a3),a2
add.w d0,a2
* Init datas
moveq #(VoiLong*4)/2-1,d0
move.l a2,a0
IMus1 clr.w (a0)+
dbra d0,IMus1
clr.w MuStop(a2)
clr.w MuStart(a2)
* Init parameters
move.l a2,d2
move.w #100,MuCpt(a2)
move.w #14,MuTempo(a2)
moveq #0,d0
IMus2 move.w #1,VoiCpt(a2)
lea FoEnd-MB(a3),a0
move.l a0,VoiAdr(a2)
move.l a1,a0
add.w 0(a0,d0.w),a0
move.l a0,VoiPat(a2)
move.l a0,VoiDPat(a2)
lea VoiLong(a2),a2
addq.w #2,d0
cmp.w #8,d0
bne.s IMus2
* Starts music
move.l d2,MuBase-MB(a3)
IMusX move.l (sp)+,a3
rts
******* Tempo T
ITempo move.l (a3)+,d0
cmp.l #100,d0
bhi IFonc
move.l MuBase(pc),d1
beq.s ITemp
move.l d1,a0
move.w d0,MuTempo(a0)
ITemp rts
***********************************************************
* =VU METRE(v)
FVu move.l (a3)+,d0
cmp.l #4,d0
bcc IFonc
lea MB(pc),a0
moveq #0,d3
move.b 0(a0,d0.w),d3
clr.b 0(a0,d0.w)
moveq #0,d2
rts
***********************************************************
* =MU BASE
FMB lea MB(pc),a0
move.l a0,d3
moveq #0,d2
rts
***********************************************************
*
* INTERRUPT ROUTINES
*
* Here is the main point! Happy SoundTracker users, forget
* everything! This music routine does not use the same system!
* Music is not coded in parallel (all note for all voices
* in 16 bytes), but in a more efficient but a little more complex
* "track" system.
* Each voice has its own track. More than that, the delays between
* each note is not fixed as in SoundTracker (to have important
* delays you just leave a few empty notes after), but coded in the
* note itself. The delay is acheived by counting this value to
* zero.
* LABEL are not coded within the note, but stands before it, in
* two bytes. The main advantage is that you can have up to 128
* different labels, and the parameter of this label is a full
* byte. More than one label can be put after each other, and will
* only have effect for the next note.
*
* This structure makes AMOS music player very versatile: it can play
* (after appropriate conversion) SoundTracker-like musics or IFF
* music files.
*
* I also realised when the music routine was finished, that it
* would not be really difficult to implement the music priority
* system, which I think is really useful to do games!
*
* If you carefully look to the code, I am sure you will be able
* to grab a few clock cycle here or there. I prefer to write readable
* code, a little slower (very little) than more efficient tricky
* code!!!
*
* For version 2 I want to implement synthetic instruments which saves
* A LOT of memory. Anyway, almost everything is ready to do so, with
* all the WAVE interrupt routines...
*
***********************************************************
******* VBL Entry
MusInt lea MB(pc),a3
move.w EnvOn-MB(a3),d0
beq Music
lea EnvBase-MB(a3),a0
lea $a0(a6),a2
moveq #0,d1
moveq #3,d2
moveq #0,d5
MuInt1 btst d1,d0
beq.s MuIntN
move.l EnvDelta(a0),d3
add.l EnvVol(a0),d3
move.l d3,EnvVol(a0)
swap d3
move.w d3,8(a2)
MuInt2 subq.w #1,EnvNb(a0)
bne.s MuIntN
bsr MuIntE
MuIntN lea EnvLong(a0),a0
lea $10(a2),a2
addq.w #1,d1
dbra d2,MuInt1
move.w d0,EnvOn-MB(a3)
move.w d5,DmaCon(a6)
******* Make noise?
tst.w Noise-MB(a3)
beq.s Music
move.w PNoise-MB(a3),d0
moveq #7,d2
move.w BSeed-MB(a3),d1
move.l WaveBase-MB(a3),a0
INoi1 add.w 6(a6),d1
mulu #$3171,d1
lsr.l #8,d1
move.w d1,WaveDeb(a0,d0.w)
subq.w #2,d0
bpl.s INoi2
move.w #LNoise-2,d0
INoi2 dbra d2,INoi1
move.w d0,PNoise-MB(a3)
move.w d1,BSeed-MB(a3)
******* Music routine
Music: move.l MuBase-MB(a3),d0
beq MuEnd1
movem.l a4-a6,-(sp)
move.l d0,a5
bsr MuEvery
* Here is a smart counter, which gives progressive results
* from zero to 100...
move.w MuCpt(a5),d0
add.w MuTempo(a5),d0
move.w d0,MuCpt(a5)
cmp.w #100,d0
bcs MuEnd
sub.w #100,MuCpt(a5)
* Lets go for one step of music!
moveq #0,d5
moveq #0,d7
move.l a5,a4
tst.b VoiCpt+1(a4)
beq.s Mus0
addq.w #1,d5
subq.b #1,VoiCpt+1(a4)
bne.s Mus0
moveq #0,d6
move.l MuChip0-MB(a3),a6
bsr MuStep
Mus0 lea MuVoix1(a5),a4
tst.b VoiCpt+1(a4)
beq.s Mus1
addq.w #1,d5
subq.b #1,VoiCpt+1(a4)
bne.s Mus1
moveq #1,d6
move.l MuChip1-MB(a3),a6
bsr MuStep
Mus1 lea MuVoix2(a5),a4
tst.b VoiCpt+1(a4)
beq.s Mus2
addq.w #1,d5
subq.b #1,VoiCpt+1(a4)
bne.s Mus2
moveq #2,d6
move.l MuChip2-MB(a3),a6
bsr MuStep
Mus2 lea MuVoix3(a5),a4
tst.b VoiCpt+1(a4)
beq.s Mus3
addq.w #1,d5
subq.b #1,VoiCpt+1(a4)
bne.s Mus3
moveq #3,d6
move.l MuChip3-MB(a3),a6
bsr MuStep
Mus3 and.w MuDMAsk-MB(a3),d7
move.w d7,$DFF096
tst.w d5
beq.s MuFin
MuEnd movem.l (sp)+,a4-a6
MuEnd1 rts
* Finished?
MuFin subq.w #1,MuNumber-MB(a3)
beq MuFini
* Restarts previous music
move.w MuNumber-MB(a3),d0
subq.w #1,d0
mulu #MuLong,d0
lea MuBuffer-MB(a3),a0
add.w d0,a0
move.l a0,MuBase-MB(a3)
move.w MuDMAsk-MB(a3),MuReStart-MB(a3)
clr.w MuStart(a0)
clr.w MuStop(a0)
bra.s MuEnd
* Really finished!
MuFini clr.l MuBase-MB(a3)
bsr.s MOff
bra.s MuEnd
* Stop sound routine
MOff lea Circuits,a0
move.w MuDMAsk-MB(a3),d0
beq.s MOf3
move.w d0,DmaCon(a0)
moveq #3,d1
MOf1 btst d1,d0
beq.s MOf2
move.w #2,$a4(a0)
clr.w $a8(a0)
MOf2 lea $10(a0),a0
dbra d1,MOf1
MOf3 rts
******* One step of music for one voice
MuStep move.l VoiAdr(a4),a2
MuSt0 move.w (a2)+,d0
bmi.s MuEtiq
* Play a normal note
move.w d0,VoiCpt(a4)
move.w (a2)+,d0
beq.s MuSt1
move.w d0,VoiNote(a4)
move.w d0,$06(a6)
move.l BankInst-MB(a3),d0
move.l VoiInst(a4),a0
add.l (a0),d0
move.l d0,(a6)
move.w 8(a0),$04(a6)
bset d6,d7
bclr d6,MuStop+1(a5)
bset d6,MuStart+1(a5)
move.w VoiSlB(a4),VoiSlide(a4)
move.w VoiSlC(a4),VoiSlB(a4)
move.b VoiVol+1(a4),0(a3,d6.w)
MuSt1 move.l a2,VoiAdr(a4)
rts
* Label entry
MuEtiq move.w d0,d1
and.w #$7F00,d0
lsr.w #6,d0
lea MuJumps(pc),a0
jmp 0(a0,d0.w)
******* Jmup table to labels
MuJumps bra EtEnd * 00-> Fin pattern
bra EtSlUp * 01-> Slide up
bra EtSlDo * 02-> Slide down
bra EtSVol * 03-> Set volume
bra MuStep * 04->
bra EtRep * 05-> Repeat
bra EtLOn * 06-> Led On
bra EtLOff * 07-> Led Off
bra EtTemp * 08-> Set Tempo
bra EtInst * 09-> Set Instrument
******* End of a pattern
EtEnd clr.w VoiCpt(a4)
clr.w VoiRep(a4)
clr.l VoiDeb(a4)
move.l VoiPat(a4),a0
RePat move.w (a0)+,d0
bmi.s EtEnd1
move.l a0,VoiPat(a4)
move.l BankPat-MB(a3),a0
cmp.w (a0),d0
bhi.s EtEndX
lsl.w #2,d0
add.w d6,d0
lsl.w #1,d0
move.w 2(a0,d0.w),d0
beq.s EtEndX
lea 0(a0,d0.w),a2
bra MuSt0
EtEndX rts
EtEnd1 cmp.w #-1,d0
beq.s EtEndX
move.l VoiDPat(a4),a0
bra.s RePat
******* Change instrument
EtInst and.w #$00FF,d1
move.l BankInst-MB(a3),a1
lsl.w #5,d1
lea 2(a1,d1.w),a1
move.l a1,VoiInst(a4)
move.w 12(a1),d0
cmp.w #64,d0
bcs.s EtInst1
moveq #63,d0
EtInst1 move.w d0,VoiDVol(a4)
mulu MuVolume-MB(a3),d0
lsr.w #6,d0
move.w d0,VoiVol(a4)
bra MuSt0
******* Slide up
EtSlUp and.w #$00FF,d1
neg.w d1
move.w d1,VoiSlide(a4)
move.w d1,VoiSlB(a4)
clr.w VoiSlC(a4)
bra MuSt0
******* Slide down
EtSlDo and.w #$00FF,d1
move.w d1,VoiSlide(a4)
move.w d1,VoiSlB(a4)
clr.w VoiSlC(a4)
bra MuSt0
******* Set Volume
EtSVol and.w #$00FF,d1
cmp.w #64,d1
bcs.s EtSVol1
moveq #63,d1
EtSVol1 move.w d1,VoiDVol(a4)
mulu MuVolume-MB(a3),d1
lsr.w #6,d1
move.w d1,VoiVol(a4)
bra MuSt0
******* Set Tempo
EtTemp and.w #$00FF,d1
move.w d1,MuTempo(a5)
bra MuSt0
******* Led On
EtLOn bclr #1,$bfe001
bra MuSt0
******* Led Off
EtLOff bset #1,$bfe001
bra MuSt0
******* Repeat
EtRep and.w #$00FF,d1
bne.s EtRep1
move.l a2,VoiDeb(a4)
bra MuSt0
EtRep1 tst.w VoiRep(a4)
bne.s EtRep2
move.w d1,VoiRep(a4)
bra MuSt0
EtRep2 subq.w #1,VoiRep(a4)
beq MuSt0
move.l VoiDeb(a4),d0
beq MuSt0
move.l d0,a2
bra MuSt0
******* Routine call every VBL
MuEvery
* Update VOLUME and FREQUENCE
move.l MuChip0-MB(a3),a6 * Voix 0
move.w VoiSlide0(a5),d0
add.w d0,VoiNote0(a5)
move.w VoiNote0(a5),$06(a6)
move.w VoiVol0(a5),$08(a6)
move.l MuChip1-MB(a3),a6 * Voix 1
move.w VoiSlide1(a5),d0
add.w d0,VoiNote1(a5)
move.w VoiNote1(a5),$06(a6)
move.w VoiVol1(a5),$08(a6)
move.l MuChip2-MB(a3),a6 * Voix 2
move.w VoiSlide2(a5),d0
add.w d0,VoiNote2(a5)
move.w VoiNote2(a5),$06(a6)
move.w VoiVol2(a5),$08(a6)
move.l MuChip3-MB(a3),a6 * Voix 3
move.w VoiSlide3(a5),d0
add.w d0,VoiNote3(a5)
move.w VoiNote3(a5),$06(a6)
move.w VoiVol3(a5),$08(a6)
* Second step of sample?
MuRsXX move.w MuStop(a5),d0
beq MuEvX
move.l BankInst-MB(a3),d1
btst #0,d0 * Voix 0
beq.s MuEv0
move.l MuChip0-MB(a3),a6
move.l VoiInst0(a5),a0
move.l d1,d2
add.l 4(a0),d2
move.l d2,(a6)
move.w 10(a0),$04(a6)
MuEv0 btst #1,d0 * Voix 1
beq.s MuEv1
move.l MuChip1-MB(a3),a6
move.l VoiInst1(a5),a0
move.l d1,d2
add.l 4(a0),d2
move.l d2,(a6)
move.w 10(a0),$04(a6)
MuEv1 btst #2,d0 * Voix 2
beq.s MuEv2
move.l MuChip2-MB(a3),a6
move.l VoiInst2(a5),a0
move.l d1,d2
add.l 4(a0),d2
move.l d2,(a6)
move.w 10(a0),$04(a6)
MuEv2 btst #3,d0 * Voix 3
beq.s MuEv3
move.l MuChip3-MB(a3),a6
move.l VoiInst3(a5),a0
move.l d1,d2
add.l 4(a0),d2
move.l d2,(a6)
move.w 10(a0),$04(a6)
MuEv3
* Start a voice
MuEvX move.w MuStart(a5),d1
move.w d1,MuStop(a5)
clr.w MuStart(a5)
or.w d1,d0
and.w MuDMAsk-MB(a3),d0
bset #15,d0
move.w d0,$DFF096
* Restart voices?
move.w MuReStart-MB(a3),d0
beq MuRsX
moveq #0,d3
btst #0,d0 * Voix 0
beq.s MuRs0
lea $DFF0A0,a6
move.l a6,MuChip0-MB(a3)
move.w #2,$04(a6)
tst.l VoiInst0(a5)
beq.s MuRs0
bset #0,d3
MuRs0 btst #1,d0 * Voix 1
beq.s MuRs1
lea $DFF0B0,a6
move.l a6,MuChip1-MB(a3)
move.w #2,$04(a6)
tst.l VoiInst1(a5)
beq.s MuRs1
bset #1,d3
MuRs1 btst #2,d0 * Voix 2
beq.s MuRs2
lea $DFF0C0,a6
move.l a6,MuChip2-MB(a3)
move.w #2,$04(a6)
tst.l VoiInst2(a5)
beq.s MuRs2
bset #2,d3
MuRs2 btst #3,d0 * Voix 3
beq.s MuRs3
lea $DFF0D0,a6
move.l a6,MuChip3-MB(a3)
move.w #2,$04(a6)
tst.l VoiInst3(a5)
beq.s MuRs3
bset #3,d3
MuRs3 clr.w MuReStart-MB(a3)
or.w d0,MuDMAsk-MB(a3)
or.w d3,MuStop(a5)
MuRsX
rts
***********************************************************
* LED INSTRUCTION
LedOn:
*******
bclr #1,$BFE001
rts
LedOf:
*******
bset #1,$BFE001
rts
***********************************************************
* MUSIC TOKEN TABLE
*
* This table is the crucial point of the extension! It tells
* everything the tokenisatioin process needs to know. You have to
* be carefull when writing it!
*
* The format is simple:
* dc.w Address of instruction-Tk,Address of function-Tk
* dc.b "instruction nam","e"+$80,"Param list",-1[or -2]
*
* 1- Address of instr/function
* You must state the one that is needed. Just put
* a 1 in the function field for an instruction, and in the
* instruction field for a function. Reserved variables need
* TWO address!
*
* 2- Instruction name
* It must be finished by the letter plus $80. Be carefull
* ARGASM assembler produces bad code if you do "a"+$80, he wants
* $80+"a"!!!
* -You can SET A MARK in the token table with a "!" before
* the name. See later
* -Using a $80 ALONE as a name definition, will force AMOS
* to point to the previous "!" mark...
*
* 3- Param list
* This list tells AMOS everything about the instruction.
*
* - First character:
* The first character defines the TYPE on instruction:
* I--> instruction
* 0--> function that returns a integer
* 1--> function that returns a float
* 2--> function that returns a string
* V--> reserved variable. In that case, you must
* state the type int-float-string
* - If your instruction does not need parameters, then you stop
* - Your instruction needs parameters, now comes the param list
* Type,TypetType,Type...
* Type of the parameter (0 1 2)
* Comma or "t" for TO
*
* 4- End of instruction
* "-1" states the end of the instruction
* "-2" tells AMOS that another parameter list
* can be accepted. if so, MUST follow the
* complete instruction definition as explained
* but with another param list.
* If so, you can use the "!" and $80 facility not to rewrite the
* full name of the instruction...See SAM LOOP ON instruction for an
* example...
*
* Remember that AMOS token list comes first, so names like:
* PRINTHELLO will never work: AMOS will tokenise PRINT first!
* Extension token list are explored in order of number...
* The next two lines NEED to be there...
Tk: dc.w 1,0
dc.b $80,-1
dc.w 1,FMB-Tk
dc.b "mubas","e"+$80,"0",-1
dc.w 1,FVu-Tk
dc.b "vumete","r"+$80,"00",-1
dc.w IVoice-Tk,1
dc.b "voic","e"+$80,"I0",-1
dc.w IMusOff-Tk,1
dc.b "music of","f"+$80,"I",-1
dc.w IMuStop-Tk,1
dc.b "music sto","p"+$80,"I",-1
dc.w ITempo-Tk,1
dc.b "temp","o"+$80,"I0",-1
dc.w IMusic-Tk,1
dc.b "musi","c"+$80,"I0",-1
dc.w INoTo-Tk,1
dc.b "noise t","o"+$80,"I0",-1
dc.w Boom-Tk,1
dc.b "boo","m"+$80,"I",-1
dc.w Shoot-Tk,1
dc.b "shoo","t"+$80,"I",-1
dc.w ISBank-Tk,1
dc.b "sam ban","k"+$80,"I0",-1
dc.w ISLOn0-Tk,1
dc.b "!sam loop o","n"+$80,"I",-2
dc.w ISLOn1-Tk,1
dc.b $80,"I",-1
dc.w ISLOf0-Tk,1
dc.b "sam loop of","f"+$80,"I",-2
dc.w ISLOf1-Tk,1
dc.b $80,"I0",-1
dc.w ISamTo-Tk,1
dc.b "sampl","e"+$80,"I0t0",-1
dc.w ISam1-Tk,1
dc.b "!sam pla","y"+$80,"I0",-2
dc.w ISam2-Tk,1
dc.b $80,"I0,0",-2
dc.w ISam3-Tk,1
dc.b $80,"I0,0,0",-1
dc.w ISamR-Tk,1
dc.b "sam ra","w"+$80,"I0,0,0,0",-1
dc.w Bell0-Tk,1
dc.b "!bel","l"+$80,"I",-2
dc.w Bell1-Tk,1
dc.b $80,"I0",-1
dc.w IPlOf0-Tk,1
dc.b "!play of","f"+$80,"I",-2
dc.w IPlOf1-Tk,1
dc.b $80,"I0",-1
dc.w IPlay2-Tk,1
dc.b "!pla","y"+$80,"I0,0",-2
dc.w IPlay3-Tk,1
dc.b $80,"I0,0,0",-1
dc.w ISWave-Tk,1
dc.b "set wav","e"+$80,"I0,2",-1
dc.w IDWave1-Tk,1
dc.b "del wav","e"+$80,"I0",-1
dc.w ISEnv-Tk,1
dc.b "set enve","l"+$80,"I0,0t0,0",-1
dc.w IMVol-Tk,1
dc.b "mvolum","e"+$80,"I0",-1
dc.w IVol1-Tk,1
dc.b "!volum","e"+$80,"I0",-2
dc.w IVol2-Tk,1
dc.b $80,"I0,0",-1
dc.w IWave-Tk,1
dc.b "wav","e"+$80,"I0t0",-1
dc.w LedOn-Tk,1
dc.b "led o","n"+$80,"I",-1
dc.w LedOf-Tk,1
dc.b "led of","f"+$80,"I",-1
dc.w ISay1-Tk,1
dc.b "!sa","y"+$80,"I2",-2
dc.w ISay2-Tk,1
dc.b $80,"I2,0",-1
dc.w ITalk-Tk,1
dc.b "set tal","k"+$80,"I0,0,0,0",-1
* You MUST finish the table by a ZERO
dc.w 0
*************** Enveloppes definitions
* Be carefull, ARGASM is bugged with __Rs!!!
RsReset
EnvNb: rs.w 1
EnvDVol: rs.w 1
EnvVol: rs.l 1
EnvDelta: rs.l 1
EnvAd: rs.l 1
EnvDeb: rs.l 1
EnvLong: equ __Rs
*************** Wave definition
LWave: equ 256+128+64+32+16+8+4+2
LNoise: equ LWave
RsReset
WaveNext: rs.l 1
WaveNb: rs.w 1
WaveEnv: rs.w 16*2
WaveDeb: rs.b LWave
WaveLong: equ __Rs
*************** Music voice data
RsReset
VoiAdr rs.l 1
VoiDeb rs.l 1
VoiInst rs.l 1
VoiDPat rs.l 1
VoiPat rs.l 1
VoiCpt rs.w 1
VoiRep rs.w 1
VoiNote rs.w 1
VoiDVol rs.w 1
VoiVol rs.w 1
VoiSlide rs.w 1
VoiSlB rs.w 1
VoiSlC rs.w 1
VoiLong equ __Rs
*************** MUBASE table
RsReset
* Voix 0
MuVoix0 equ __Rs
VoiAdr0 rs.l 1
VoiDeb0 rs.l 1
VoiInst0 rs.l 1
VoiDPat0 rs.l 1
VoiPat0 rs.l 1
VoiCpt0 rs.w 1
VoiRep0 rs.w 1
VoiNote0 rs.w 1
VoiDVol0 rs.w 1
VoiVol0 rs.w 1
VoiSlide0 rs.w 1
VoiSlB0 rs.w 1
VoiSlC0 rs.w 1
* Voix 1
MuVoix1 equ __Rs
VoiAdr1 rs.l 1
VoiDeb1 rs.l 1
VoiInst1 rs.l 1
VoiDPat1 rs.l 1
VoiPat1 rs.l 1
VoiCpt1 rs.w 1
VoiRep1 rs.w 1
VoiNote1 rs.w 1
VoiDVol1 rs.w 1
VoiVol1 rs.w 1
VoiSlide1 rs.w 1
VoiSlB1 rs.w 1
VoiSlC1 rs.w 1
* Voix 2
MuVoix2 equ __Rs
VoiAdr2 rs.l 1
VoiDeb2 rs.l 1
VoiInst2 rs.l 1
VoiDPat2 rs.l 1
VoiPat2 rs.l 1
VoiCpt2 rs.w 1
VoiRep2 rs.w 1
VoiNote2 rs.w 1
VoiDVol2 rs.w 1
VoiVol2 rs.w 1
VoiSlide2 rs.w 1
VoiSlB2 rs.w 1
VoiSlC2 rs.w 1
* Voix 3
MuVoix3 equ __Rs
VoiAdr3 rs.l 1
VoiDeb3 rs.l 1
VoiInst3 rs.l 1
VoiDPat3 rs.l 1
VoiPat3 rs.l 1
VoiCpt3 rs.w 1
VoiRep3 rs.w 1
VoiNote3 rs.w 1
VoiDVol3 rs.w 1
VoiVol3 rs.w 1
VoiSlide3 rs.w 1
VoiSlB3 rs.w 1
VoiSlC3 rs.w 1
* Other data
MuCpt rs.w 1
MuTempo rs.w 1
MuStart rs.w 1
MuStop rs.w 1
* Total length
MuLong equ __Rs
*************** MUSIC extension data zone
even
MB:
MuVu dc.l 0 * Vu Meters
MuBase dc.l 0 * Curretn music address
MusAdr dc.l 0 * Branch table address
MusClock dc.l 3546895 * Clock speed
WaveBase dc.l 0 * Wave tree
Waves dc.w 0,0,0,0
EnvOn: dc.w 0 * ADSR running?
EnvBase: ds.b EnvLong*4 * ADSR table
SamBank: dc.w 0 * Sample bank
BSeed: dc.w 0 * Random seed
Noise: dc.w 0 * Noise on?
PNoise: dc.w 0 * Pointer to noise buffer
* Musique
MusBank dc.l 0 * Music bank
MusCheck dc.l 0 * Check sum
BankInst dc.l 0 * Instruments
BankSong dc.l 0 * Songs
BankPat dc.l 0 * Patterns
MuNumber dc.w 0 * Music priority
MuVolume dc.w 0 * Music volume
MuDMAsk dc.w 0 * Voice mask
MuReStart dc.w 0 * Restart the voice
MuChip0 dc.l 0 * Circuits 0
MuChip1 dc.l 0 * 1
MuChip2 dc.l 0 * 2
MuChip3 dc.l 0 * 3
FoEnd dc.w $8000 * Fake empty pattern
MuBuffer ds.b MuLong*3 * Music tables
*************** Default enveloppes
EnvDef: dc.w 1,64,4,55,5,50,25,0,0,0
EnvShoot dc.w 1,64,10,0,0,0
EnvBoom dc.w 1,64,10,50,50,0,0,0
EnvBell dc.w 1,64,4,40,25,0,0,0
*************** Sample enveloppes
EnvSam dc.w 1,64,1,64,0,0,0,0
dc.w 1,64,1,64,0,0,0,0
dc.w 1,64,1,64,0,0,0,0
dc.w 1,64,1,64,0,0,0,0
*************** Bank headers
BkSam: dc.b "Samples "
BkMus: dc.b "Music "
*************** Frequency / notes
TFreq: dc.w 000,256/2
dc.w 000,256/2
dc.w 256,128/2
dc.w 384,64/2
dc.w 448,32/2
dc.w 480,16/2
dc.w 496,8/2
dc.w 504,4/2
dc.w 504,4/2
TNotes: dc.w 00,00,00,33,35,37,39,41,44,46,49,52
dc.w 55,58,62,65,69,73,78,82,87,92,98,104
dc.w 110,117,123,131,139,147,156,165,175,185,196,208
dc.w 220,233,247,262,277,294,311,330,349,370,392,415
dc.w 440,466,494,523,554,587,622,659,698,740,784,830
dc.w 880,932,988,1046,1109,1175,1245,1319,1397,1480,1568,1661
dc.w 1760,1865,1986,2093,2217,2349,2489,2637,2794,2960,3136,3322
dc.w 3520,3729,3952,4186,4435,4699,4978,5274,5588,5920,6272,6645
dc.w 7040,7459,7902,8372
*************** NARRATOR
Amaps: dc.b 3,5,10,12
TranBase dc.l 0
TalkIO: ds.l 20
WriteRep: ds.l 8
TranName dc.b "translator.library",0
NarDevice dc.b "narrator.device",0
*************** Welcome message
* 27 Y,position is like locate ,position...
MusWel: dc.b 27,"Y8Music player V 1.1",0
*************** ERROR MESSAGES
MusErr: dc.b "Wave not defined",0 *0
dc.b "Sample not defined",0 *1
dc.b "Sample bank not found",0 *2
dc.b "256 characters for a wave",0 *3
dc.b "Wave 0 and 1 are reserved",0 *4
dc.b "Music bank not found",0 *5
dc.b "Music not defined",0 *6
dc.b "Can't open narrator",0 *7
*************** That's it!
dc.l 0